﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;
using jaysJourney_v01.States;
using Microsoft.Xna.Framework;
using System.Diagnostics;

namespace jaysJourney_v01.Utils
{
    class InputGroup
    {
        /**
         * MEMBER VARIABLES
         * */

        // From Parent

        private List<Button> buttonList;
        private State parentState;
        private SpriteBatch parentSpriteBatch;

        // Common

        private MouseState curMouseState;
        private KeyboardState curKeyboardState;
        private static MouseState prevMouseState;
        private static KeyboardState prevKeyboardState;
        private GamePadState curPadState;
        private static GamePadState prevPadState;

        private int activeButton = 0;

        /**
         * METHODS
         * */

        // Constructor

        public InputGroup(State parentS, SpriteBatch sb)
        {
            this.parentState = parentS;
            this.parentSpriteBatch = sb;

            buttonList = new List<Button>();
        }

        // MAIN UPDATE

        public Button update(GameTime gameTime)
        {
            curKeyboardState = Keyboard.GetState();
            curMouseState = Mouse.GetState();
            curPadState = GamePad.GetState(PlayerIndex.One);

            var mousePosition = new Point(curMouseState.X, curMouseState.Y);

            for (int i = 0; i < this.buttonList.Count; i++)
            {
                Button button = this.buttonList[i];

                //activate button
                if (button.getActive() || button is InputField)
                {
                    if (button is InputField) ((InputField)button).update();
                    else button.update();
                }

                // hover over button
                if (button.getRectangle().Contains(mousePosition)) { this.activeButton = i; }

                // keyboard
                if (curKeyboardState.IsKeyDown(Keys.Up) && prevKeyboardState.IsKeyUp(Keys.Up) || curKeyboardState.IsKeyDown(Keys.Left) && prevKeyboardState.IsKeyUp(Keys.Left) || curPadState.IsButtonDown(Buttons.DPadUp) && prevPadState.IsButtonUp(Buttons.DPadUp) || curPadState.IsButtonDown(Buttons.DPadLeft) && prevPadState.IsButtonUp(Buttons.DPadLeft))
                {
                    this.activeButton--;
                    prevKeyboardState = curKeyboardState;
                    prevPadState = curPadState;
                    if(this.activeButton < 0) this.activeButton = this.buttonList.Count - 1;
                }
                else if (curKeyboardState.IsKeyDown(Keys.Down) && prevKeyboardState.IsKeyUp(Keys.Down) || curKeyboardState.IsKeyDown(Keys.Right) && prevKeyboardState.IsKeyUp(Keys.Right) || curPadState.IsButtonDown(Buttons.DPadDown) && prevPadState.IsButtonUp(Buttons.DPadDown) || curPadState.IsButtonDown(Buttons.DPadRight) && prevPadState.IsButtonUp(Buttons.DPadRight))
                {
                    this.activeButton++;
                    prevKeyboardState = curKeyboardState;
                    prevPadState = curPadState;
                    if(this.activeButton >= this.buttonList.Count) this.activeButton = 0;
                }
                else if (curKeyboardState.IsKeyDown(Keys.Tab) && prevKeyboardState.IsKeyUp(Keys.Tab)) // switch inputfields
                {
                    if (button is InputField && ((InputField)button).getActiveInput()) // this button is active
                    {
                        int counter = i + 1;
                        while(counter < this.buttonList.Count)
                        {
                            if (buttonList[counter] is InputField) // found next input
                            {
                                ((InputField)button).setActiveInput(false); // deactivate current button
                                ((InputField)buttonList[counter]).setActiveInput(true); // activate new button
                                prevKeyboardState = curKeyboardState;
                                break;
                            }
                            counter++;
                        }
                        if (counter == this.buttonList.Count) // no next input found, search before current button
                        {
                            for (int j = 0; j < i; j++)
                            {
                                if (buttonList[j] is InputField)
                                {
                                    ((InputField)button).setActiveInput(false); // deactivate current button
                                    ((InputField)buttonList[j]).setActiveInput(true); // activate new button
                                    prevKeyboardState = curKeyboardState;
                                    break;
                                }
                            }
                        }
                    }
                }

                // set active button
                if (i == this.activeButton) button.setActive(true);
                else button.setActive(false);

                // trigger button
                if (button.getActive() == true && ((curKeyboardState.IsKeyDown(Keys.Enter) && prevKeyboardState.IsKeyUp(Keys.Enter) || curPadState.IsButtonDown(Buttons.A) && prevPadState.IsButtonUp(Buttons.A)))) // Hit Enter
                {
                    prevKeyboardState = curKeyboardState;
                    prevPadState = curPadState;

                    foreach (Button btn in buttonList) { if (btn is InputField) ((InputField)btn).setActiveInput(false); } // set all input inactive
                    if (button is InputField) ((InputField)button).setActiveInput(true); // activate input and leave input active

                    return button;
                }
                else if (prevMouseState.LeftButton == ButtonState.Released && curMouseState.LeftButton == ButtonState.Pressed && button.getRectangle().Contains(new Rectangle(mousePosition.X, mousePosition.Y, 1, 1))) // click on button
                {
                    prevMouseState = curMouseState;

                    foreach (Button btn in buttonList) { if (btn is InputField) ((InputField)btn).setActiveInput(false); } // set all input inactive
                    if (button is InputField) ((InputField)button).setActiveInput(true); // activate input and leave input active

                    return button;
                }
            }

            prevMouseState = curMouseState;
            prevKeyboardState = curKeyboardState;
            prevPadState = curPadState;

            return null; // no Button clicked
        }

        // MAIN DRAW

        public void draw(GameTime gameTime)
        {
            foreach (Button button in buttonList)
            {
                if (button is InputField) ((InputField)button).draw();
                else
                {
                    button.draw();
                    if(button.getShowTxt()) button.drawName(Color.White);
                }
            }
        }

        // add new Button to list

        public void addButton(Button bt)
        {
            this.buttonList.Add(bt);
            bt.addSpriteBatch(this.parentSpriteBatch);
        }

        // return content

        public String getContent(String buttonName)
        {
            foreach (Button button in buttonList)
            {
                if (button is InputField && button.getName() == buttonName) return ((InputField)button).getContent();
            }

            return buttonName + " does not exist!";
        }

        // reset inputFields

        public void resetInputField()
        {
            foreach (Button button in buttonList)
            {
                if (button is InputField) ((InputField)button).resetContent();
            }
        }

        // clear buttons

        public void emptyGroup()
        {
            this.buttonList.Clear();
        }

        public List<Button> getButtonList()
        {
            return this.buttonList;
        }
    }
}
